Add ObjectName wrapper to solve hashing issues
authorFelix Krull <f_krull@gmx.de>
Wed, 3 Oct 2018 13:22:48 +0000 (15:22 +0200)
committerColin Walters <walters@verbum.org>
Fri, 6 May 2022 16:53:53 +0000 (12:53 -0400)
rust-bindings/rust/libostree/src/lib.rs
rust-bindings/rust/libostree/src/object_name.rs [new file with mode: 0644]
rust-bindings/rust/libostree/src/repo.rs
rust-bindings/rust/sample/src/main.rs

index cca9c9cabd7c4574c7b2d078391b10ac504c6fa0..62dafff98fe75bb32f691eaf8887c9526f723fc3 100644 (file)
@@ -20,6 +20,9 @@ pub use auto::functions::*;
 
 mod repo;
 
+mod object_name;
+pub use object_name::ObjectName;
+
 // public modules
 pub mod prelude {
     pub use auto::traits::*;
diff --git a/rust-bindings/rust/libostree/src/object_name.rs b/rust-bindings/rust/libostree/src/object_name.rs
new file mode 100644 (file)
index 0000000..0524663
--- /dev/null
@@ -0,0 +1,59 @@
+use ffi;
+use functions::object_name_deserialize;
+use glib;
+use glib_ffi;
+use glib::translate::*;
+use ObjectType;
+use std::fmt::Display;
+use std::fmt::Error;
+use std::fmt::Formatter;
+use std::hash::Hash;
+use std::hash::Hasher;
+use functions::object_to_string;
+
+fn hash_object_name(v: &glib::Variant) -> u32 {
+    unsafe { ffi::ostree_hash_object_name(v.to_glib_none().0 as glib_ffi::gconstpointer) }
+}
+
+#[derive(PartialEq, Eq, Debug)]
+pub struct ObjectName {
+    variant: glib::Variant,
+    checksum: String,
+    object_type: ObjectType,
+}
+
+impl ObjectName {
+    pub fn new(variant: glib::Variant) -> ObjectName {
+        let deserialize = object_name_deserialize(&variant);
+        ObjectName {
+            variant,
+            checksum: deserialize.0,
+            object_type: deserialize.1,
+        }
+    }
+
+    pub fn checksum(&self) -> &str {
+        self.checksum.as_ref()
+    }
+
+    pub fn object_type(&self) -> ObjectType {
+        self.object_type
+    }
+
+    pub fn name(&self) -> String {
+        object_to_string(self.checksum(), self.object_type())
+            .expect("type checks should make this safe")
+    }
+}
+
+impl Display for ObjectName {
+    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
+        write!(f, "{}", self.name())
+    }
+}
+
+impl Hash for ObjectName {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        state.write_u32(hash_object_name(&self.variant));
+    }
+}
index 5bce9fe0206b98c6633f6ff26c5c5c7c67e4413c..272c9002b147f8eae5714626b57cc6099562b346 100644 (file)
@@ -8,19 +8,19 @@ use glib::translate::*;
 use glib_ffi;
 use std::collections::HashSet;
 use std::ptr;
-
+use ObjectName;
 
 unsafe extern "C" fn read_variant_table(_key: glib_ffi::gpointer, value: glib_ffi::gpointer, hash_set: glib_ffi::gpointer) {
     let value: glib::Variant = from_glib_none(value as *const glib_ffi::GVariant);
     // TODO: this set is degenerate because g_variant_hash for my Variants is always 0
-    let set: &mut HashSet<glib::Variant> = &mut *(hash_set as *mut HashSet<glib::Variant>);
-    set.insert(value);
+    let set: &mut HashSet<ObjectName> = &mut *(hash_set as *mut HashSet<ObjectName>);
+    set.insert(ObjectName::new(value));
 }
 
 
-unsafe fn from_glib_container_variant_set(ptr: *mut glib_ffi::GHashTable) -> HashSet<glib::Variant> {
+unsafe fn from_glib_container_variant_set(ptr: *mut glib_ffi::GHashTable) -> HashSet<ObjectName> {
     let mut set = HashSet::new();
-    glib_ffi::g_hash_table_foreach(ptr, Some(read_variant_table), &mut set as *mut HashSet<glib::Variant> as *mut _);
+    glib_ffi::g_hash_table_foreach(ptr, Some(read_variant_table), &mut set as *mut HashSet<ObjectName> as *mut _);
     glib_ffi::g_hash_table_unref(ptr);
     set
 }
@@ -28,11 +28,11 @@ unsafe fn from_glib_container_variant_set(ptr: *mut glib_ffi::GHashTable) -> Has
 
 pub trait RepoExtManual {
     fn new_for_str(path: &str) -> Repo;
-    fn traverse_commit_manual<'a, P: Into<Option<&'a gio::Cancellable>>>(
+    fn traverse_commit<'a, P: Into<Option<&'a gio::Cancellable>>>(
         &self,
         commit_checksum: &str,
         maxdepth: i32,
-        cancellable: P) -> Result<HashSet<glib::Variant>, Error>;
+        cancellable: P) -> Result<HashSet<ObjectName>, Error>;
 }
 
 impl<O: IsA<Repo> + IsA<glib::Object> + Clone + 'static> RepoExtManual for O {
@@ -40,12 +40,12 @@ impl<O: IsA<Repo> + IsA<glib::Object> + Clone + 'static> RepoExtManual for O {
         Repo::new(&gio::File::new_for_path(path))
     }
 
-    fn traverse_commit_manual<'a, P: Into<Option<&'a gio::Cancellable>>>(
+    fn traverse_commit<'a, P: Into<Option<&'a gio::Cancellable>>>(
         &self,
         commit_checksum: &str,
         maxdepth: i32,
         cancellable: P,
-    ) -> Result<HashSet<glib::Variant>, Error> {
+    ) -> Result<HashSet<ObjectName>, Error> {
         unsafe {
             let mut error = ptr::null_mut();
             let mut hashtable = ptr::null_mut();
index e6da49e161aea93bd07000d8d70d3f9bfa0d0f67..a42d52ac584e72795bba810686b3ddd632646a0b 100644 (file)
@@ -21,25 +21,21 @@ fn main() {
 
     println!("sha256: {}", checksum);
 
-    let objs = repo.traverse_commit_manual(checksum.as_str(), -1, None).unwrap();
+    let objs = repo.traverse_commit(checksum.as_str(), -1, None).unwrap();
 
     for obj in objs {
-        let (name, obj_type) = libostree::object_name_deserialize(&obj);
-        println!("  {}", libostree::object_to_string(name.as_str(), obj_type).unwrap());
+        //let (name, obj_type) = libostree::object_name_deserialize(&obj);
+        println!("  {}", obj.name());
 
-        let (stream, size) = repo.load_object_stream(obj_type, name.as_str(), None).unwrap();
+        let (stream, size) = repo.load_object_stream(obj.object_type(), obj.checksum(), None).unwrap();
         println!("  bytes: {}", size);
 
-        if obj_type == libostree::ObjectType::File {
-            let mut file = File::create("./object.file").unwrap();
-            let mut read = 1;
-            let mut buffer = [0 as u8; 4096];
-            while read != 0 {
-                read = stream.read(buffer.as_mut(), None).unwrap();
-                file.write(&buffer[0 .. read]);
-            }
+        let mut file = File::create(obj.name()).unwrap();
+        let mut read = 1;
+        let mut buffer = [0 as u8; 4096];
+        while read != 0 {
+            read = stream.read(buffer.as_mut(), None).unwrap();
+            file.write(&buffer[0 .. read]).unwrap();
         }
-
-        //println!("{:?}", obj.type_());
     }
 }